unsigned int frameCount; // counter for number of frames printed
[self stopHandlingCrashes]; // Try to avoid re-entry problems
// Start the frame pointer off at our frame
framePointer = ((void *) &self)-8;
frameCount=0;
// Assume that a whole lotta frames means either (a) we're trashed or
// (b) we're in a recursive deathtrap. In the latter case, we've
// probably got enough info to see a whole cycle.
while (frameCount<MAX_FRAMES && framePointer) {
// If this frame is a method call we'll have a valid
// selector at (fp+12).
if (sel_isMapped(*(SEL *)(framePointer+12))) {
[self printMethodFromFP:framePointer];
} else {
[self printFunctionFromFP:framePointer];
}
framePointer = (void *)*(long *)framePointer; // go up one frame
}
return self;
}
+ dumpBacktrace:(const char *)message
{
NXLogError("%s", message);
NXLogError("Here's the stack frame Backtrace:");
[self printBacktrace];
return self;
}
static void handle_signal(int signal)
{
const char *msg=NULL;
char buf[1024];
SignalItem *cur;
msg = "Unrecognized signal";
for (cur = signals; cur->number; cur++) {
if (cur->number==signal) {
msg = cur->message;
break;
}
}
sprintf(buf, "Caught signal #%d: \"%s\"", signal, msg);
[ObjectError dumpBacktrace:buf];
if (!muddleOn) {
exit(1);
}
[ObjectError tryToContinue];
}
- error:(const char *)aString, ...
{
va_list ap;
char buffer[1024];
va_start(ap, aString);
vsprintf(buffer, aString, ap);
va_end(ap);
if (!ignoreCrashes) [[self class] dumpBacktrace:buffer];
if (muddleOn)
{
[[self class] tryToContinue];
return self;
}
return [super error:buffer];
}
+ error:(const char *)aString, ...
{
va_list ap;
char buffer[1024];
va_start(ap, aString);
vsprintf(buffer, aString, ap);
va_end(ap);
if (!ignoreCrashes) [[self class] dumpBacktrace:buffer];
if (muddleOn)
{
[self tryToContinue];
return self;
}
return [super error:buffer];
}
+ tryToContinue;
{
int i;
ignoreCrashes = NO;
NXLogError("Trying to continue...");
i = NXRunAlertPanel("Internal Error","An internal error has occurred. Try to save work, then quit and restart the application.","Continue","Quit",NULL);
if (i == NX_ALERTALTERNATE) exit(1);
[NXApp abortModal];
return self;
}
#define ON 1
#define OFF 0
SignalItem signals[] = {
{SIGHUP, OFF, "Hangup"},
{SIGINT, OFF, "Interrupt"},
{SIGQUIT, ON, "Quit"},
{SIGILL, ON, "Illegal instruction"},
{SIGTRAP, ON, "Trace trap"},
{SIGIOT, ON, "IOT instruction"},
{SIGEMT, ON, "EMT instruction"},
{SIGFPE, ON, "Floating point exception"},
{SIGKILL, OFF, "Kill"},
{SIGBUS, ON, "Bus error"},
{SIGSEGV, ON, "Segmentation violation"},
{SIGSYS, ON, "Bad argument to system call"},
{SIGPIPE, OFF, "Write on a pipe with no one to read it"},
{SIGALRM, OFF, "Alarm clock"},
{SIGTERM, OFF, "Software termination"},
{SIGURG, OFF, "Urgent condition present on socket"},
{SIGSTOP, OFF, "Stop"},
{SIGTSTP, OFF, "Stop signal generated from keyboard"},
{SIGCONT, OFF, "Continue after stop"},
{SIGCHLD, OFF, "Child status changed"},
{SIGTTIN, OFF, "Background read attempted from control terminal"},
{SIGTTOU, OFF, "Background write attempted to control terminal"},